package com.mcxx.modules.common.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.mcxx.common.exception.BizException;
import com.mcxx.constant.DictConstant;
import com.mcxx.modules.base.service.read.DictionaryReadService;
import com.mcxx.modules.filemanage.file.service.FileService;
import com.mcxx.modules.miniSalvation.check.dto.*;
import com.mcxx.modules.miniSalvation.check.entity.CheckEntity;
import com.mcxx.modules.miniSalvation.check.service.read.CheckReadService;
import com.mcxx.modules.miniSalvation.check.service.read.DepartmentDataReadService;
import com.mcxx.modules.miniSalvation.check.service.write.CheckWriteService;
import com.mcxx.modules.miniSalvation.family.service.read.FamilyMemberHistoryReadService;
import com.mcxx.modules.miniSalvation.family.service.read.FamilyMemberReadService;
import com.mcxx.modules.miniSalvation.family.service.read.FamilySupportReadService;
import com.mcxx.modules.miniSalvation.order.dto.CheckDTO;
import com.mcxx.modules.miniSalvation.order.service.read.OrderCertReadService;
import com.mcxx.modules.miniSalvation.order.service.read.OrderReadService;
import com.mcxx.modules.miniSalvation.order.service.write.RecheckBatchWriteService;
import com.mcxx.modules.temporary.family.service.read.TmpFamilyMemberReadService;
import com.mcxx.modules.temporary.order.service.read.TmpOrderCertReadService;
import com.mcxx.modules.temporary.order.service.read.TmpOrderReadService;
import com.mcxx.util.*;
import com.yinhai.ta404.core.security.vo.UserAccountVo;
import com.yinhai.ta404.core.transaction.annotation.TaTransactional;
import com.yinhai.ta404.module.dict.entity.TaDictPo;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;


@Service
@TaTransactional
public class IntegrateCheckServiceImpl {
    private final static Logger logger = LoggerFactory.getLogger(IntegrateCheckServiceImpl.class);
    @Autowired
    private FamilyMemberReadService familyMemberReadService;
    @Autowired
    private FamilyMemberHistoryReadService familyMemberHistoryReadService;
    @Autowired
    private OrderCertReadService orderCertReadService;
    @Autowired
    private CheckWriteService checkWriteService;
    @Autowired
    private CheckReadService checkReadService;
    @Autowired
    private OrderReadService orderReadService;
    @Autowired
    private TmpOrderReadService tmpOrderReadService;
    @Autowired
    private TmpFamilyMemberReadService tmpFamilyMemberReadService;
    @Autowired
    private TmpOrderCertReadService tmpOrderCertReadService;
    @Autowired
    private DictionaryReadService dictionaryReadService;
    @Autowired
    private FileService fileService;
    @Autowired
    private FamilySupportReadService familySupportReadService;
    @Autowired
    private RecheckBatchWriteService recheckBatchWriteService;
    @Autowired
    private DepartmentDataReadService departmentDataReadService;

    @Value("${integrate.appKey:society-check}")
    private String appKey;
    @Value("${integrate.appSecurity:mcxx1234}")
    private String appSecurity;
    @Value("${integrate.url:http://59.231.230.27:16008/mc-check}")
    private String url;
    @Value("${integrate.sendCheck:/check/apply/saveCheck}")
    private String sendCheck;
    @Value("${integrate.queryCheck:/check/report/queryReport}")
    private String queryCheck;
    @Value("${integrate.repealCheck:/check/apply/cancelCheck}")
    private String repealCheck;

    public String startCheck(List<CheckDTO> checkDTOList,String businessCode,String areaCode,UserAccountVo accountVo,String checkType){
        Map<String,String> header = new HashMap<>();
        header.put("username",accountVo.getUserId());
        header.put("areaCode",areaCode);
        header.put("appKey",appKey);
        header.put("appSecurity",appSecurity);

        String checkBatchNo = checkDTOList.stream().map(checkDTO -> checkDTO.getCheckBatchNo()).findFirst().get();
        String resMsg = "";


        if(Constant.BusinessCode.DIBAO.equals(businessCode) || Constant.BusinessCode.TEKUN.equals(businessCode) ){

            List<IntegrateCheckDTO> checkDTOS = this.queryMiniCheckInfo(checkDTOList, accountVo,checkType);
            resMsg = this.sendHttp(checkDTOS,header,url+sendCheck,checkBatchNo);
        }else{

            List<IntegrateCheckDTO> checkDTOS = this.queryTmpCheckInfo(checkDTOList, accountVo);
            resMsg = this.sendHttp(checkDTOS,header,url+sendCheck,checkBatchNo);
        }
      return  resMsg;
    }

    public List<IntegrateCheckDTO> queryMiniCheckInfo(List<CheckDTO> checkDTOList,UserAccountVo accountVo,String checkType){

        List<String> orderIds = checkDTOList.stream().map(checkDTO -> checkDTO.getOrderId()).collect(Collectors.toList());

        List<IntegrateCheckDTO> integrateCheckInfo = orderReadService.getIntegrateCheckInfo(orderIds);

        boolean supportFlag  = true;
        if("0".equals(checkDTOList.get(0).getFamilySupport())){
            supportFlag = false;
        }

        for(IntegrateCheckDTO checkDTO:integrateCheckInfo){

            String checkId = checkDTOList.stream().filter(o -> o.getOrderId().equals(checkDTO.getOrderId())).map(o -> o.getCheckId()).findFirst().get();
            checkDTO.setCheckId(checkId);

            checkDTO.setUserCode(accountVo.getUserId());

            checkDTO.setRequestType(Constant.CheckRequestType.SALVATION);

            if(Constant.UserLevel.STREET.equals(accountVo.getAreaLevel())){
                checkDTO.setIsVillage("1");
            }else{
                checkDTO.setIsVillage("0");
            }

            List<String> authorFile = orderCertReadService.getIntegrateAuthorFile(Constant.FileType.CHECK_EMPOWER,checkDTO.getOrderId());
            if(null != authorFile && authorFile.size()>0){
                checkDTO.setProxyStatement(authorFile.get(0));
            }
            List<IntegrateCheckMemberDTO> memberDTO = null;

            if(Constant.CheckType.BATCH_RECHECK.equals(checkType)){
                checkDTO.setType(Constant.CheckType.RECHECK);
                memberDTO = familyMemberHistoryReadService.selectIntegrateMember(checkDTO.getOrderId(),checkDTO.getFamilyId());
            }else {
                memberDTO = familyMemberReadService.selectIntegrateMember(checkDTO.getOrderId(),checkDTO.getFamilyId());
            }
            for(IntegrateCheckMemberDTO dto:memberDTO){


                TaDictPo taDictPo = dictionaryReadService.getCodeCache(DictConstant.MARRY_STATE,dto.getMarried());
                dto.setMarried(taDictPo.getLabel());

                taDictPo = dictionaryReadService.getCodeCache(DictConstant.FM_RELATION,dto.getRelation());
                dto.setRelation(taDictPo.getLabel());
                dto.setType(checkDTO.getType());
            }
            checkDTO.setMemberList(memberDTO);

            if(supportFlag){
                List<IntegrateCheckMemberDTO> supportMemberList = familySupportReadService.seletcSupportForIntegrate(checkDTO.getOrderId(),checkDTO.getFamilyId());
                for(IntegrateCheckMemberDTO supportMember : supportMemberList){
                    supportMember.setType(checkDTO.getType());
                }
                memberDTO.addAll(supportMemberList);
            }
        }
       return integrateCheckInfo;
    }

    public List<IntegrateCheckDTO> queryTmpCheckInfo(List<CheckDTO> checkDTOList,UserAccountVo accountVo){

        List<String> orderIds = checkDTOList.stream().map(checkDTO -> checkDTO.getOrderId()).collect(Collectors.toList());

        List<IntegrateCheckDTO> integrateCheckInfo = tmpOrderReadService.getIntegrateCheckInfo(orderIds);

        for(IntegrateCheckDTO checkDTO:integrateCheckInfo){

            String checkId = checkDTOList.stream().filter(o -> o.getOrderId().equals(checkDTO.getOrderId())).map(o -> o.getCheckId()).findFirst().get();
            checkDTO.setCheckId(checkId);

            checkDTO.setUserCode(accountVo.getUserId());

            checkDTO.setRequestType(Constant.CheckRequestType.SALVATION);

            List<String> authorFile = tmpOrderCertReadService.getIntegrateAuthorFile(Constant.FileType.CHECK_EMPOWER,checkDTO.getOrderId());
            if(null != authorFile && authorFile.size()>0){
                checkDTO.setProxyStatement(authorFile.get(0));
            }
            List<IntegrateCheckMemberDTO> memberDTO = tmpFamilyMemberReadService.selectIntegrateMember(checkDTO.getOrderId(),checkDTO.getFamilyId());
            for(IntegrateCheckMemberDTO dto:memberDTO){


                TaDictPo taDictPo = dictionaryReadService.getCodeCache(DictConstant.MARRY_STATE,dto.getMarried());
                dto.setMarried(taDictPo.getLabel());

                taDictPo = dictionaryReadService.getCodeCache(DictConstant.FM_RELATION,dto.getRelation());
                dto.setRelation(taDictPo.getLabel());
                dto.setType(checkDTO.getType());
            }
            checkDTO.setMemberList(memberDTO);
        }
        return integrateCheckInfo;
    }

    public String startDepartmentCheck(List <CheckEntity> entities, UserAccountVo accountVo){
        Map<String,String> header = new HashMap<>();
        header.put("username",accountVo.getUserId());
        header.put("areaCode",accountVo.getAreaCode());
        header.put("appKey",appKey);
        header.put("appSecurity",appSecurity);
        String nowMonth = DateUtil.sdf2.format(new Date()).substring(0,8)+"01";

        List<String> ids = entities.stream().map(o->o.getOrderId()).collect(Collectors.toList());
        String checkBatchNo = entities.get(0).getCheckBatchNo();
        List<IntegrateCheckDTO> checkDTOS = departmentDataReadService.selectCheckInfo(ids);
        for(IntegrateCheckDTO checkDTO:checkDTOS){
            String orderId = checkDTO.getOrderId();
            String checkId = entities.stream().filter(o->orderId.equals(o.getOrderId())).findFirst().get().getCheckId();
            checkDTO.setCheckId(checkId);

            checkDTO.setRequestType(Constant.CheckRequestType.OTHER);

            checkDTO.setUserCode(accountVo.getUserId());

            if(Constant.UserLevel.STREET.equals(accountVo.getAreaLevel())){
                checkDTO.setIsVillage("1");
            }else{
                checkDTO.setIsVillage("0");
            }

            List<String> authorFile = orderCertReadService.getIntegrateAuthorFile(Constant.FileType.CHECK_EMPOWER,checkDTO.getOrderId());
            if(null != authorFile && authorFile.size()>0){
                checkDTO.setProxyStatement(authorFile.get(0));
            }

            IntegrateCheckMemberDTO memberDTO = new IntegrateCheckMemberDTO();
            memberDTO.setIdCard(checkDTO.getIdCard());
            memberDTO.setSex(IdCardUtil.getSex(checkDTO.getIdCard()));
            memberDTO.setName(checkDTO.getName());
            memberDTO.setRelation("本人");
            memberDTO.setIsSalv(Constant.IsSaveObject.NO);

            Integer i  = familyMemberHistoryReadService.selectIsSalvByIdcard(checkDTO.getIdCard(),nowMonth);
            if(null!=i && i>0){
                memberDTO.setIsSalv(Constant.IsSaveObject.YES);
            }

            List<String> idcardFile = orderCertReadService.getIntegrateAuthorFile(Constant.FileType.IDCARD,checkDTO.getOrderId());
            if(null != authorFile && authorFile.size()>0){
                memberDTO.setIdCardFile(idcardFile.get(0));
            }
            List<IntegrateCheckMemberDTO> list = Arrays.asList(memberDTO);
            checkDTO.setMemberList(list);
        }
        String resMsg = this.sendHttp(checkDTOS,header,url+sendCheck,checkBatchNo);
        return resMsg;
    }

    public String sendHttp(List<IntegrateCheckDTO> dtos,Map<String,String> header,String url,String checkBatchNo){

        String res = null;

        Gson gson = new Gson();
        String dtoString = gson.toJson(dtos);
        logger.info("核对一体化请求报文req：{}",dtoString);
        logger.info("header:{}",header);
        try {
            res = OkHttpUtil.doPostWithHeader(url,dtoString,header);
        } catch (Exception e) {
            logger.error("发起核对一体化请求异常"+e);

            checkWriteService.updateCheckStateByBatchNo(checkBatchNo,null,"核对接口异常",Constant.CheckState.CHECK_EXCEPTION);
            return "发起核对一体化失败";
        }
        logger.info("核对委托响应res:{}",res);
        JSONObject resJSON = null;
        try {
            resJSON = JSONObject.parseObject(res);
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("发起核对一体化响应转换json异常");

            checkWriteService.updateCheckStateByBatchNo(checkBatchNo,null,"核对一体化响应数据异常",Constant.CheckState.CHECK_EXCEPTION);
            return "发起核对一体化失败";
        }

        if(resJSON==null||resJSON.containsKey("code")==false){
            checkWriteService.updateCheckStateByBatchNo(checkBatchNo,null,"核对一体化响应码为空",Constant.CheckState.CHECK_EXCEPTION);
            logger.info("核对一体化响应码为空");
            return "发起核对失败";
        }
        String resCode = resJSON.getString("code");
        logger.info("核对一体化响应码 {}",resCode);
        if("200".equals(resCode)){

            checkWriteService.updateCheckStateByBatchNo(checkBatchNo,null,null,Constant.CheckState.CITYRECEIVE);
            return "发起核对成功";
        }else if("-1".equals(resCode)){

            JSONArray resultArray = resJSON.getJSONArray("result");
            logger.info("核对一体化result{}",resultArray);
            if(null!=resultArray && resultArray.size()>0){

                StringBuffer sb = new StringBuffer();

                List<String> checkId = new ArrayList<>();
                for(int i=0;i<resultArray.size();i++){
                    String failCheckId = resultArray.getJSONObject(i).getString("checkId");
                    String errorMsg = resultArray.getJSONObject(i).getString("errorMessage");
                    checkId.add(failCheckId);

                    checkWriteService.updateCheckStateById(Arrays.asList(failCheckId),errorMsg,Constant.CheckState.CHECK_EXCEPTION);

                    String idcard = dtos.stream().filter(o->o.getCheckId().equals(failCheckId)).findFirst().get().getIdCard();
                    sb.append("身份证为"+idcard+"的家庭"+errorMsg+";");
                }

                checkWriteService.updateCheckStateByBatchNo(checkBatchNo,checkId,null,Constant.CheckState.CITYRECEIVE);

                String resMsg = sb.toString();
                return resMsg.substring(0,resMsg.length()-1);
            }
            return "发起核对成功";
        }else{

            checkWriteService.updateCheckStateByBatchNo(checkBatchNo,null,"核对一起化发起失败",Constant.CheckState.CHECK_EXCEPTION);
            String resMsg = "发起核对失败,核对响应码为"+resCode;
            if(resJSON.containsKey("message")){
                resMsg += ";错误信息为"+resJSON.getString("message");
            }
            return resMsg;
        }
    }

    public String queryCheckFile(String checkId,String orderId,UserAccountVo accountVo){
        Map<String,String> header = new HashMap<>();
        header.put("username",accountVo.getUserId());
        header.put("areaCode",accountVo.getAreaCode());
        header.put("appKey",appKey);
        header.put("appSecurity",appSecurity);
        JSONObject reqJson = new JSONObject();
        reqJson.put("checkId",checkId);
        reqJson.put("orderId",orderId);
        reqJson.put("userCode",accountVo.getLoginId());
        String res = OkHttpUtil.doPostWithHeader(url+queryCheck,reqJson.toJSONString(),header);
        logger.info("获取核对一体化核对报告：{}",res);
        JSONObject  resJson = JSONObject.parseObject(res);
        if(resJson.containsKey("code") && "200".equals(resJson.getString("code"))){
            return resJson.getString("result");
        }else{
            return "获取核对报告失败";
        }
    }

    public int saveIntegratedCheckFile(MultipartFile[] files, String checkId){

        if(files==null||files.length<1){
            throw new BizException("-1","没有核对文件");
        }
        int res = 0;
        try{
            String [] keys = new String[files.length];
            int i = 0;
            String objectkey = fileService.upload(files[0].getInputStream(), files[0].getOriginalFilename());
            CheckEntity check  = new CheckEntity();
            check.setCheckId(checkId);
            check.setCheckReportFile(objectkey);
            check.setSaveDate(new Date());
            CheckEntity checKEntity = checkReadService.selectById(checkId);

            if(Constant.CheckRequestType.OTHER.equals(checKEntity.getBusinessType())){
                check.setIntegratStatus(Constant.IntegrateCheckStatus.CONFERED);
                check.setConferDate(new Date());
                check.setReportTime(new Date());
                check.setCheckState(Constant.CheckState.FORWARD_RESULT);
            }else{
                check.setIntegratStatus(Constant.IntegrateCheckStatus.WAIT_CONFER);
            }
            res = checkWriteService.updateCheckByCheckId(check);
        }catch(IOException e){
            e.printStackTrace();
            throw new BizException(FailureCode.ERR_20078);
        }
        return res;
    }

    public int repealCheck(CheckEntity checkEntity,UserAccountVo accountVo){
        checkEntity = checkReadService.selectById(checkEntity.getCheckId());
        Map<String,String> header = new HashMap<>();
        header.put("username",accountVo.getUserId());
        header.put("areaCode",accountVo.getAreaCode());
        header.put("appKey",appKey);
        header.put("appSecurity",appSecurity);
        JSONObject reqJson = new JSONObject();
        reqJson.put("checkId",checkEntity.getCheckId());
        reqJson.put("orderId",checkEntity.getOrderId());
        reqJson.put("familyId",checkEntity.getFamilyId());
        reqJson.put("remark","中止核对");
        String res = OkHttpUtil.doPostWithHeader(url+repealCheck,reqJson.toJSONString(),header);
        logger.info("取消一体化核对：{}",res);
        JSONObject  resJson = JSONObject.parseObject(res);
        if(resJson.containsKey("code") && "200".equals(resJson.getString("code"))){
            CheckEntity entity = new CheckEntity();
            entity.setCheckId(checkEntity.getCheckId());
            entity.setCheckState(Constant.CheckState.END_CHECK);
            entity.setCheckResultState(Constant.CheckState.END_CHECK);
            checkWriteService.updateIgnoreNull(entity);
            recheckBatchWriteService.updateStateByCheckId(checkEntity.getCheckId());
            return 1;
        }else{
            return 0;
        }
    }


    public String sendDepartmentCheck(List<DepartmentDataDTO> dtos,UserAccountVo userAccountVo){

        List<String> ids =  dtos.stream().map(o->o.getId()).collect(Collectors.toList());

        List<String> nocertIdcards = orderCertReadService.selectDepartmentMustCert(ids);

        dtos = dtos.stream().filter(dto-> !nocertIdcards.contains(dto.getIdcard())).collect(Collectors.toList());

        String resMsg = "";

        if(CollectionUtils.isNotEmpty(nocertIdcards) && nocertIdcards.size()>0){
            resMsg = "身份证为"+String.join(",",nocertIdcards)+"的对象不存在授权书/身份证，不能发起核对；";
        }
        if(dtos.size()>0){

            List<CheckEntity> entities = checkWriteService.addDepartmentCheck(dtos, userAccountVo.getAreaCode());

            resMsg += startDepartmentCheck(entities,userAccountVo);
        }
        return resMsg;
    }
}
